package com.tang.nacos.config;

/**
 * @Author tanglingyu
 * @Date: 2021/04/06/ 15:21
 * @Description
 */

import com.alibaba.druid.pool.DruidDataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.ComplexShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.google.common.collect.Lists;

/**
 * sharding 数据源
 *
 * @author zhaolei
 * @date 2020年12月3日
 */
@Configuration
public class ShardingDataSourceConfig {

  @Value("${spring.shardingsphere.dataSource.names}")
  String dbNames;

  @Autowired
  private Environment env;

  private Map<String, DataSource> dataSourceMap = new HashMap<>();

  @Bean(name = "shardingDateSource")
  public DataSource getDataSource() throws SQLException {
    return buildDataSource();
  }

  private DataSource buildDataSource() throws SQLException {
    initDataSourceMap();
    int dbNums = dbNames.split(",").length - 1;

    // 具体分库分表策略,按什么规则来分
    ShardingRuleConfiguration conf = new ShardingRuleConfiguration();

    // table rule
    TableRuleConfiguration tableRule = new TableRuleConfiguration("user",
        "ds$->{0.." + dbNums + "}.user_$->{0..1}");

    // key生成规则
    KeyGeneratorConfiguration keyGen = new KeyGeneratorConfiguration("SNOWFLAKE", "id");
    tableRule.setKeyGeneratorConfig(keyGen);

    // 分表策略
    ComplexShardingStrategyConfiguration tableShardingStrategyConfig = new ComplexShardingStrategyConfiguration(
        "id,age", new MyTableShardingAlgorithm());
    tableRule.setTableShardingStrategyConfig(tableShardingStrategyConfig);

    // 自定义分库策略
    ComplexShardingStrategyConfiguration myDatabaseShardingStrategy = new ComplexShardingStrategyConfiguration(
        "id,age", new MyDatabaseShardingAlgorithm());
    conf.setDefaultDatabaseShardingStrategyConfig(myDatabaseShardingStrategy);

    conf.setTableRuleConfigs(Lists.newArrayList(tableRule));
    Properties props = new Properties();
    props.put("sql.show", true);

    DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, conf, props);

    return dataSource;

  }

  public void initDataSourceMap() {
    System.out.println(dbNames);
    for (String name : dbNames.split(",")) {
      DruidDataSource ds = new DruidDataSource();
      ds.setDriverClassName(
          env.getProperty("spring.shardingsphere.dataSource." + name + ".driver-class-name"));
      System.out.println(
          env.getProperty("spring.shardingsphere.dataSource." + name + ".driver-class-name"));
      ds.setUrl(env.getProperty("spring.shardingsphere.dataSource." + name + ".url"));
      System.out.println(env.getProperty("spring.shardingsphere.dataSource." + name + ".jdbc-url"));
      ds.setUsername(env.getProperty("spring.shardingsphere.dataSource." + name + ".username"));
      System.out.println(env.getProperty("spring.shardingsphere.dataSource." + name + ".username"));
      ds.setPassword(env.getProperty("spring.shardingsphere.dataSource." + name + ".password"));
      System.out.println(env.getProperty("spring.shardingsphere.dataSource." + name + ".password"));
      dataSourceMap.put(name, ds);
    }
    System.out.println(dataSourceMap);
  }
}
